﻿using Mapster;
using Microsoft.AspNetCore.Mvc;
using PARK.CardAcct.Entitys;
using PARK.ClayObject;
using PARK.Common.Configuration;
using PARK.Common.Core.Manager;
using PARK.Common.Enum;
using PARK.Common.Extension;
using PARK.Common.Filter;
using PARK.Common.Helper;
using PARK.Common.Model.NPOI;
using PARK.Consumer.Entity;
using PARK.Consumer.Entitys.Dto.ConsumBill;
using PARK.Consumer.Interfaces.ConsumBill;
using PARK.DataEncryption;
using PARK.Dependency;
using PARK.DynamicApiController;
using PARK.FriendlyException;
using PARK.JsonSerialization;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace PARK.Consumer
{
    /// <summary>
    /// 消费记录服务
    /// </summary>
    [ApiDescriptionSettings(Tag = "Consum", Name = "ConsumBill", Order = 200)]
    [Route("api/consum/[controller]")]
    public class ConsumBillService : IConsumBillService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<ConsumBillEntity> _consumBillRepository;
        private readonly SqlSugarScope _db;
        private readonly IUserManager _userManager;

        /// <summary>
        /// 初始化一个<see cref="ConsumBillService"/>类型的新实例
        /// </summary>
        public ConsumBillService(
            ISqlSugarRepository<ConsumBillEntity> consumBillRepository,
            IUserManager userManager)
        {
            _consumBillRepository = consumBillRepository;
            _db = _consumBillRepository.Context;
            _userManager = userManager;
        }

        /// <summary>
        /// 获取消费记录
        /// </summary>
        /// <param name="id">参数</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<dynamic> GetInfo(string id)
        {
            var entity = await _db.Queryable<ConsumBillEntity>().FirstAsync(p => p.Id == id);
            var output = entity.Adapt<ConsumBillInfoOutput>();
            return output;
        }

        /// <summary>
		/// 获取消费记录列表
		/// </summary>
		/// <param name="input">请求参数</param>
		/// <returns></returns>
        [HttpGet("")]
        public async Task<dynamic> GetList([FromQuery] ConsumBillListQueryInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                if (input.departId == userInfo.companyId)
                {
                    input.departId = null;
                }
                var sidx = input.sidx == null ? "SortCode" : input.sidx;
                List<string> queryTxnDate = input.txnDate != null ? input.txnDate.Split(',').ToObeject<List<string>>() : null;
                DateTime? startTxnDate = queryTxnDate != null ? Ext.GetDateTime(queryTxnDate.First()) : null;
                DateTime? endTxnDate = queryTxnDate != null ? Ext.GetDateTime(queryTxnDate.Last()) : null;
                var data = await _db.Queryable<ConsumBillEntity>()
                    .Where(p => p.CompanyId.Equals(userInfo.companyId))//权限
                    .WhereIF(!string.IsNullOrEmpty(input.machineNo), p => p.MachineNo.Contains(input.machineNo))
                    .WhereIF(!string.IsNullOrEmpty(input.machineId), p => p.MachineId.Contains(input.machineId))
                    .WhereIF(!string.IsNullOrEmpty(input.merchantId), p => p.MerchantId.Contains(input.merchantId))
                    .WhereIF(!string.IsNullOrEmpty(input.cardTypeId), p => p.CardTypeId.Contains(input.cardTypeId))
                    .WhereIF(!string.IsNullOrEmpty(input.timeIntervalId), p => p.TimeIntervalId.Contains(input.timeIntervalId))                    
                    .WhereIF(!string.IsNullOrEmpty(input.cardNo), p => p.CardNo.Contains(input.cardNo))
                    .WhereIF(!string.IsNullOrEmpty(input.keyword), p => p.JobNo.Contains(input.keyword) || p.ReallName.Contains(input.keyword) || p.CatCardNo.Contains(input.keyword))
                    .WhereIF(!string.IsNullOrEmpty(input.departId), p => p.DepartId .Contains(input.departId))
                    .WhereIF(queryTxnDate != null, u => u.TxnDate >= new DateTime(startTxnDate.ToDate().Year, startTxnDate.ToDate().Month, startTxnDate.ToDate().Day, 0, 0, 0))
                    .WhereIF(queryTxnDate != null, u => u.TxnDate <= new DateTime(endTxnDate.ToDate().Year, endTxnDate.ToDate().Month, endTxnDate.ToDate().Day, 23, 59, 59))
                    .WhereIF(!string.IsNullOrEmpty(input.payWay), p => p.PayWay.Equals(input.payWay))
                    .Select(it => new ConsumBillListOutput
                    {
                        id = it.Id,
                        merchantName = it.MerchantName,
                        cardNo = it.CardNo,
                        catCardNo =it.CatCardNo,
                        employeeId = it.EmployeeId,
                        jobNo = it.JobNo,
                        reallName = it.ReallName,
                        departName = it.DepartName,
                        txnTotalAmt = it.TxnTotalAmt,
                        txnSeq = it.TxnSeq,
                        txnDate = Convert.ToDateTime(it.TxnDate).ToString("yyyy-MM-dd HH:mm:ss"),
                        txnResult = it.TxnResult,
                        requestId = it.RequestId,
                        payWay = it.PayWay,
                        consumKind = it.ConsumKind.Value,
                        uploadTime = it.UploadTime,
                        machineName=it.MachineName,
                        timeIntervalName = it.TimeIntervalName,
                        cardTypeName = it.CardTypeName,
                        SortCode = it.SortCode                        
                    }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
                return PageResult<ConsumBillListOutput>.SqlSugarPageResult(data);
            }
            else
                return null;
        }

        #region 导出消费记录Excel
        /// <summary>
        /// 获取消费记录无分页列表
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [NonAction]
        public async Task<dynamic> GetNoPagingList([FromQuery] ConsumBillListQueryInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            var sidx = input.sidx == null ? "id" : input.sidx;
            List<string> queryTxnDate = input.txnDate != null ? input.txnDate.Split(',').ToObeject<List<string>>() : null;
            DateTime? startTxnDate = queryTxnDate != null ? Ext.GetDateTime(queryTxnDate.First()) : null;
            DateTime? endTxnDate = queryTxnDate != null ? Ext.GetDateTime(queryTxnDate.Last()) : null;
            var data = await _db.Queryable<ConsumBillEntity>()
                .Where(p => p.CompanyId.Equals(userInfo.companyId))//权限
                .WhereIF(!string.IsNullOrEmpty(input.machineNo), p => p.MachineNo.Contains(input.machineNo))
                .WhereIF(!string.IsNullOrEmpty(input.machineId), p => p.MachineId.Contains(input.machineId))
                .WhereIF(!string.IsNullOrEmpty(input.merchantId), p => p.MerchantId.Contains(input.merchantId))
                .WhereIF(!string.IsNullOrEmpty(input.cardTypeId), p => p.CardTypeId.Contains(input.cardTypeId))
                .WhereIF(!string.IsNullOrEmpty(input.timeIntervalId), p => p.TimeIntervalId.Contains(input.timeIntervalId))
                .WhereIF(!string.IsNullOrEmpty(input.cardNo), p => p.CardNo.Contains(input.cardNo))
                .WhereIF(!string.IsNullOrEmpty(input.keyword), p => p.JobNo.Contains(input.keyword) || p.ReallName.Contains(input.keyword) || p.CatCardNo.Contains(input.keyword))
                .WhereIF(!string.IsNullOrEmpty(input.departId), p => p.DepartId.Contains(input.departId))
                .WhereIF(queryTxnDate != null, u => u.TxnDate >= new DateTime(startTxnDate.ToDate().Year, startTxnDate.ToDate().Month, startTxnDate.ToDate().Day, 0, 0, 0))
                .WhereIF(queryTxnDate != null, u => u.TxnDate <= new DateTime(endTxnDate.ToDate().Year, endTxnDate.ToDate().Month, endTxnDate.ToDate().Day, 23, 59, 59))
                .WhereIF(!string.IsNullOrEmpty(input.payWay), p => p.PayWay.Equals(input.payWay))
                .Select(it => new ConsumBillListOutput
                {
                    id = it.Id,
                    merchantName = it.MerchantName,
                    cardNo = it.CardNo,
                    catCardNo = it.CatCardNo,
                    employeeId = it.EmployeeId,
                    jobNo = it.JobNo,
                    reallName = it.ReallName,
                    departName = it.DepartName,
                    txnTotalAmt = it.TxnTotalAmt,
                    txnSeq = it.TxnSeq,
                    txnDate = Convert.ToDateTime(it.TxnDate).ToString("yyyy-MM-dd HH:mm:ss"),
                    txnResult = it.TxnResult,
                    requestId = it.RequestId,
                    payWay = it.PayWay,
                    consumKind = it.ConsumKind.Value,
                    uploadTime = it.UploadTime,
                    machineName = it.MachineName,
                    timeIntervalName = it.TimeIntervalName,
                    cardTypeName =it.CardTypeName
                }).MergeTable().OrderBy(sidx + " " + input.sort).ToListAsync();
            return data;

        }

        /// <summary>
        /// 导出消费记录
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [HttpGet("Actions/Export")]
        public async Task<dynamic> Export([FromQuery] ConsumBillListQueryInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            var exportData = new List<ConsumBillListOutput>();
            var exportDataNew = new List<ConsumBillListOutput>();
            if (input.dataType == 0)
            {
                var data = Clay.Object(await this.GetList(input));
                exportData = data.Solidify<PageResult<ConsumBillListOutput>>().list;
            }
            else
            {
                exportData = await this.GetNoPagingList(input);
            }

            foreach (ConsumBillListOutput item in exportData)
            {
                var etxnResult = "";
                if (item.txnResult == 1)
                {
                    etxnResult = "成功";
                }
                else if (item.txnResult == 0)
                {
                    etxnResult = "失败";
                }

                var epayWay = "";
                if (item.payWay == 0)
                {
                    epayWay = "在线";
                }
                else if (item.payWay == 1)
                {
                    epayWay = "离线";
                }
                item.etxnResult = etxnResult;
                item.epayWay = epayWay;
                exportDataNew.Add(item);
            }

            List<ParamsModel> paramList = "[{\"value\":\"请求扣费流水\",\"field\":\"requestId\"},{\"value\":\"商户名称\",\"field\":\"merchantName\"},{\"value\":\"消费机\",\"field\":\"machineName\"},{\"value\":\"消费卡号\",\"field\":\"cardNo\"},{\"value\":\"卡面卡号\",\"field\":\"catCardNo\"},{\"value\":\"工号\",\"field\":\"jobNo\"},{\"value\":\"姓名\",\"field\":\"reallName\"},{\"value\":\"卡片类型\",\"field\":\"cardTypeName\"},{\"value\":\"部门\",\"field\":\"departName\"},{\"value\":\"消费额\",\"field\":\"txnTotalAmt\"},{\"value\":\"交易时间\",\"field\":\"txnDate\"},{\"value\":\"交易结果\",\"field\":\"etxnResult\"},{\"value\":\"交易类型\",\"field\":\"epayWay\"},{\"value\":\"餐次\",\"field\":\"timeIntervalName\"},{\"value\":\"摘要\",\"field\":\"summary\"}]".ToList<ParamsModel>();
            ExcelConfig excelconfig = new ExcelConfig();
            excelconfig.FileName = userInfo.companyName + "_" + "消费记录" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls";
            excelconfig.HeadFont = "微软雅黑";
            excelconfig.HeadPoint = 10;
            excelconfig.IsAllSizeColumn = true;
            excelconfig.ColumnModel = new List<ExcelColumnModel>();
            List<string> selectKeyList = input.selectKey.Split(',').ToList();
            foreach (var item in selectKeyList)
            {
                var isExist = paramList.Find(p => p.field == item);
                if (isExist != null)
                {
                    excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = isExist.field, ExcelColumn = isExist.value });
                }
            }
            var addPath = FileVariable.TemporaryFilePath + excelconfig.FileName;
            ExcelExportHelper<ConsumBillListOutput>.Export(exportDataNew, excelconfig, addPath);
            var fileName = _userManager.UserId + "|" + addPath + "|xls";
            var output = new
            {
                name = excelconfig.FileName,
                url = "api/file/Download?encryption=" + DESCEncryption.Encrypt(fileName, "JNPF") //"wwwroot/Template/TemporaryFile/" + excelconfig.FileName //
            };
            return output;
        }
        #endregion

        #region Post 补扣消费
        /// <summary>
        /// 补扣消费
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("")]
        public async Task Create([FromBody] ConsdeductInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                if (string.IsNullOrEmpty(input.EmployeeId))
                {
                    throw PARKException.Bah("请选择补扣人员!");
                }
                else
                {
                    //消费机
                    var _ConsumMachine = await _db.Queryable<ConsumMachineEntity>().FirstAsync(p => p.MachineId == input.MachineId);
                    if (_ConsumMachine == null)
                    {
                        throw PARKException.Bah("请选择补扣消费机!");
                    }
                    else
                    {
                        var _Employee = await _db.Queryable<EmployeeEntity>().FirstAsync(p => p.EmployeeId == input.EmployeeId);
                        if (_Employee != null)
                        {
                            var _RequestId = YitIdHelper.NextId().ToString();
                            var _CardNo = _Employee.CardNo;
                            var _TxnDate = input.TxnDate;
                            var _MachineSerialNum = _ConsumMachine.MachineSerialNum;
                            var _summary = (string.IsNullOrEmpty(input.summary) ? "手工补扣" : input.summary) + ";" + userInfo.userName;
                            var Paras = new List<SugarParameter>();
                            Paras.Add(new SugarParameter("@RequestId", _RequestId));
                            Paras.Add(new SugarParameter("@ConsumKind", 1));
                            Paras.Add(new SugarParameter("@TxnTotalAmt", 0));
                            Paras.Add(new SugarParameter("@CardNo", _CardNo));
                            Paras.Add(new SugarParameter("@MachineSerialNum", _MachineSerialNum));
                            Paras.Add(new SugarParameter("@TxnDate", _TxnDate));
                            Paras.Add(new SugarParameter("@Txnflag", 1));
                            Paras.Add(new SugarParameter("@PayWay", 1));
                            Paras.Add(new SugarParameter("@payOut", null, true));
                            Paras.Add(new SugarParameter("@Summary", _summary));
                            _db.Ado.UseStoredProcedure().ExecuteCommand("P_Payfor_Add", Paras);
                            object _obj = Paras[8].Value;
                            if (_obj == null || int.Parse(_obj.ToString().Split(",".ToCharArray())[0]) < 1)
                                throw PARKException.Bah("消费补扣录入失败!");
                        }
                        else
                        {
                            throw PARKException.Bah("补扣人员不存在!");
                        }
                    }
                }
            }
            else
                throw PARKException.Bah("您的权限无法操作!");
        }
        #endregion
    }
}
